/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: Frank
 * 系统版本: 1.0.0
 * 开发人员: Frank
 * 开发时间: 2019/12/20 23:29
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.spring.arch.uaa.oauth2.handler;

import com.spring.arch.common.exception.AppRuntimeException;
import com.spring.arch.uaa.oauth2.bean.SecurityUser;
import com.spring.arch.common.exception.AppRuntimeException;
import com.spring.arch.uaa.oauth2.bean.SecurityUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.StringJoiner;

/**
 * 登录身份验证提供者
 * - 重写additionalAuthenticationChecks，支持密码加盐
 *
 * @author Frank
 * @version 1.0.0.1
 * @since 2019/12/20 23:29
 */
public class LoginAuthenticationProvider extends DaoAuthenticationProvider {

    public LoginAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
        super();
        setUserDetailsService(userDetailsService);
        setPasswordEncoder(passwordEncoder);
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        if (authentication.getCredentials() == null) {
            logger.error("Authentication failed: no credentials provided");
            throw new AppRuntimeException("no credentials provided, Authentication failed!!!");
        }

        String presentedPassword = authentication.getCredentials().toString();

        if (userDetails instanceof SecurityUser) {
            SecurityUser securityUser = (SecurityUser) userDetails;
            String salt = securityUser.getSalt();
            if (StringUtils.isNotBlank(salt)) {
                presentedPassword = new StringJoiner("$")
                        .add(presentedPassword)
                        .add(salt)
                        .toString();
            }
        }

        if (!getPasswordEncoder().matches(presentedPassword, userDetails.getPassword())) {
            logger.error("Authentication failed: password does not match stored value");
            throw new AppRuntimeException("Bad credentials, Authentication failed!!!");
        }
    }
}
